package cn.edu.buaa.nlsde.mpj.fw.model;

import cn.edu.buaa.nlsde.mpj.fw.model.input.Inputs;
import cn.edu.buaa.nlsde.mpj.fw.model.output.Outputs;
import cn.edu.buaa.nlsde.mpj.fw.model.parameter.Parameter;
import cn.edu.buaa.nlsde.mpj.fw.model.parameter.Parameters;
import cn.edu.buaa.nlsde.mpj.fw.model.procedure.Procedure;
import cn.edu.buaa.nlsde.mpj.fw.model.procedure.Procedures;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class Model {
    private String name;
    private String description;
    private Inputs inputs;
    private Parameters parameters;
    private Outputs outputs;
    private Procedures procedures;

    private Map<String, String> forJEvalUse;

    public Model() {
        forJEvalUse = new HashMap<String, String>();
    }

    public Model(String name, String description, Inputs inputs,
                 Parameters parameters, Outputs outputs, Procedures procedures) {
        this();
        setName(name);
        setDescription(description);
        setInputs(inputs);
        setParameters(parameters);
        setProcedures(procedures);
        setOutputs(outputs);
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Inputs getInputs() {
        return inputs;
    }

    public void setInputs(Inputs inputs) {
        this.inputs = inputs;
        for (Map.Entry<String, Variable> entry : inputs.collection().entrySet()) {
            this.forJEvalUse.put(entry.getKey(), null);
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Outputs getOutputs() {
        return outputs;
    }

    public void setOutputs(Outputs outputs) {
        this.outputs = outputs;
    }

    public Parameters getParameters() {
        return parameters;
    }

    public void setParameters(Parameters parameters) {
        this.parameters = parameters;
        for (Entry<String, Variable> entry : parameters.collection().entrySet()) {
            Parameter parameter = (Parameter) entry.getValue();
            this.forJEvalUse.put(parameter.getName(), parameter.getValue());
        }
    }

    public Procedures getProcedures() {
        return procedures;
    }

    public void setProcedures(Procedures procedures) {
        this.procedures = procedures;
    }


    public Map<String, String> getForJEvalUse() {
        return forJEvalUse;
    }

    public void print() {
        System.out.println("-----------------------------" + getName() + "------------------------------");
        System.out.println("模型名称:" + getName());
        System.out.println("模型描述:" + getDescription());
        System.out.println("模型输入变量：");
        printVariable(getInputs());
        System.out.println("模型参数：");
        printVariable(getParameters());
        System.out.println("模型输出变量");
        printVariable(getOutputs());
        System.out.println("模型计算表达式：");
        printProcedure(getProcedures());
        System.out.println("-----------------------------" + forBeauty(getName().length()) + "------------------------------");
    }

    //验证模型是否合法
    public boolean check() {
        //TODO:验证模型有效性
        return true;
    }

    private static void printVariable(Variables variables) {
        System.out.println("\t变量名\t\t类型\t\t取值");
        for (Variable variable : variables.collection().values()) {
            System.out.println("\t" + StringUtils.rightPad(variable.getName(), 12)
                    + StringUtils.rightPad(variable.getType(), 8)
                    + StringUtils.rightPad(variable.getValue(), 8));
        }
    }

    private static void printProcedure(Procedures procedures) {
        if (procedures.size() > 0) {
            for (Procedure procedure : procedures.collection().values()) {
                System.out.println("\t" + "名称：" + procedure.getName());
                System.out.println("\t" + "表达式：" + procedure.getExpression());
                System.out.println("\t" + "返回值名称：" + procedure.getReturnName());
            }
        }
    }

    private String forBeauty(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append("-");
        }
        return sb.toString();
    }

}
